package com.ai.wx.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ai.core.constant.GlobalConstant;
import com.ai.core.dao.BaseDaoI;
import com.ai.core.util.Configure;
import com.ai.core.util.StringUtil;
import com.ai.wx.entity.AgentBrokerage;
import com.ai.wx.entity.AgentBrokerageDtl;
import com.ai.wx.entity.AgentUser;
import com.ai.wx.entity.ProductOrder;
import com.ai.wx.entity.ProductOrderPre;
import com.ai.wx.entity.WxNotifyLog;
import com.ai.wx.handler.RequestHandler;
import com.ai.wx.service.AgentService;
import com.ai.wx.service.ProductOrderService;

@Service
public class ProductOrderServiceImpl implements ProductOrderService {

	@Autowired
	private BaseDaoI<AgentUser> agentUserDao;
	@Autowired
	private BaseDaoI<ProductOrder> productOrderDao;
	@Autowired
	private BaseDaoI<ProductOrderPre> productOrderPreDao;
	@Autowired
	private BaseDaoI<WxNotifyLog> wxNotifyLogDao;
	@Autowired
	private BaseDaoI<AgentBrokerage> agentBrokerageDao;
	@Autowired
	private BaseDaoI<AgentBrokerageDtl> agentBrokerageDtlDao;

	@Autowired
	private AgentService agentService;
	

	public List<ProductOrder> getProdOrderList(String openId, Integer orderState, int page, int rows) {
		String hql = "from ProductOrder where openid =:openid and state = 1";

		HashMap params = new HashMap();
		params.put("openid", openId);
		if (orderState != null && orderState.intValue() != 0) {
			hql += "orderState =:orderState";
			params.put("orderState", orderState);
		}
		hql += " order by id desc";
		List<ProductOrder> list = productOrderDao.find(hql, params, page, rows);
		return list;
	}

	public ProductOrder getOrderByOutTradeId(String outTradeNo) {
		String hql = "from ProductOrder where outTradeNo =:outTradeNo and state = 1";

		HashMap params = new HashMap();
		params.put("outTradeNo", outTradeNo);
		ProductOrder order = productOrderDao.get(hql, params);
		return order;
	}

	public ProductOrderPre getOrderPreByOutTradeId(String outTradeNo) {
		String hql = "from ProductOrderPre where outTradeNo =:outTradeNo and state = 1";

		HashMap params = new HashMap();
		params.put("outTradeNo", outTradeNo);
		ProductOrderPre order = productOrderPreDao.get(hql, params);
		return order;
	}

	@Override
	public void createOrderPre(ProductOrderPre order) {
		productOrderPreDao.save(order);
	}

	@Override
	public String processWxPayNotify(Map<String, String> map, HttpServletRequest request, HttpServletResponse response) {
		WxNotifyLog wxNotifyLog = new WxNotifyLog();
		wxNotifyLog.setAppid(map.get("appid"));
		wxNotifyLog.setReturnCode(map.get("return_code"));
		wxNotifyLog.setReturnMsg(map.get("return_msg"));
		wxNotifyLog.setMchId(map.get("mch_id"));
		wxNotifyLog.setDeviceInfo(map.get("device_info"));
		wxNotifyLog.setNonceStr(map.get("nonce_str"));
		wxNotifyLog.setSign(map.get("sign"));
		wxNotifyLog.setResultCode(map.get("result_code"));
		wxNotifyLog.setErrCode(map.get("err_code"));
		wxNotifyLog.setErrCodeDes(map.get("err_code_des"));
		wxNotifyLog.setOpenid(map.get("openid"));
		wxNotifyLog.setIsSubscribe(map.get("is_subscribe"));
		wxNotifyLog.setTradeType(map.get("trade_type"));
		wxNotifyLog.setBankType(map.get("bank_type"));
		wxNotifyLog.setTotalFee(map.get("total_fee"));
		wxNotifyLog.setCouponFee(map.get("coupon_fee"));
		wxNotifyLog.setFeeType(map.get("fee_type"));
		wxNotifyLog.setTransactionId(map.get("transaction_id"));
		wxNotifyLog.setOutTradeNo(map.get("out_trade_no"));
		wxNotifyLog.setAttach(map.get("attach"));
		wxNotifyLog.setTimeEnd(map.get("time_end"));
		wxNotifyLogDao.save(wxNotifyLog);

		String appId = map.get("appid");
		// String returnCode = map.get("return_code");
		String resultCode = map.get("result_code");
		if (StringUtils.equals(Configure.getAppId(), appId)) {
			if (StringUtils.equals(resultCode, "SUCCESS")) {// 支付成功
				// 商户订单号
				String outTradeNo = map.get("out_trade_no");
				// 财付通订单号
				String transactionId = map.get("transaction_id");
				// 金额,以分为单位
				String totalFeeStr = map.get("total_fee");
				int totalFee = StringUtil.parseInt(totalFeeStr);

				ProductOrderPre orderPre = getOrderPreByOutTradeId(outTradeNo);
				if (orderPre == null) {//如果没有查到，则认为该订单不存在或者已经处理
					return RequestHandler.setXML("SUCCESS", "");

				} else {
					orderPre.setTransactionId(transactionId);

					if (totalFee == orderPre.getPrice()) {// 费用一致
						orderPre.setOrderState(GlobalConstant.ORDER_STATE_PAY_SUCEEESS);
						saveOrderByOrderPre(orderPre);

						return RequestHandler.setXML("SUCCESS", "");
					} else {
						String msg = "应收：" + orderPre.getPrice() + ";实收：" + totalFee + ";两者费用不一致";
						orderPre.setOrderState(GlobalConstant.ORDER_STATE_PAY_WITH_ERROR);
						orderPre.setOrderMsg(msg);
						saveOrderByOrderPre(orderPre);
						return RequestHandler.setXML("FAIL", msg);
					}
				}

			} else {
				return RequestHandler.setXML("SUCCESS", "");
			}
		} else {// sha1签名失败

			return RequestHandler.setXML("FAIL", "APPID与系统记录不一致");
		}

	}

	private void saveOrderByOrderPre(ProductOrderPre orderPre) {
		ProductOrder order = tranToProductOrder(orderPre);
		productOrderDao.save(order);
		productOrderPreDao.delete(orderPre);
	}

	private ProductOrder tranToProductOrder(ProductOrderPre orderPre) {
		ProductOrder order = new ProductOrder();
		order.setOutTradeNo(orderPre.getOutTradeNo());
		order.setTransactionId(orderPre.getTransactionId());
		order.setPrepayId(orderPre.getPrepayId());
		order.setOpenid(orderPre.getOpenid());
		order.setProductId(orderPre.getProductId());
		order.setOrderDate(orderPre.getOrderDate());
		order.setTariff(orderPre.getTariff());
		order.setPrice(orderPre.getPrice());
		order.setDiscount(orderPre.getDiscount());
		order.setBrokerage(orderPre.getBrokerage());
		order.setMobile(orderPre.getMobile());
		order.setRate(orderPre.getRate());
		order.setPromotionCode(orderPre.getPromotionCode());
		order.setAgentId(orderPre.getAgentId());
		order.setOrderState(orderPre.getOrderState());
		order.setOrderMsg(orderPre.getOrderMsg());
		return order;
	}

	@Override
    public List<ProductOrder> batchDoProductOrder() {
		String processFlag = UUID.randomUUID().toString();
		String sql = "update product_order set process_flag = :processFlag where order_state = "+GlobalConstant.ORDER_STATE_PAY_SUCEEESS+" and state = 1 and process_flag is  null limit 10";

		HashMap params = new HashMap();
		params.put("processFlag", processFlag); 
		productOrderDao.executeSql(sql, params); 
		String hql = "from ProductOrder where process_flag = :processFlag"; 
		List<ProductOrder> list = productOrderDao.find(hql, params); 
		return list;
    }

	@Override
    public void productOrderSuccess(ProductOrder order) {
		order.setOrderState(GlobalConstant.ORDER_STATE_OK);
		productOrderDao.update(order);
		
		if(StringUtils.isNotEmpty(order.getPromotionCode())){//如果优惠码不为空，则需要计算酬金
			Integer agentId = order.getAgentId();
			if(agentId !=null && agentId.intValue() >0){
				AgentBrokerage agentBrokerage = agentService.getAgentBrokerage(agentId);
				if(agentBrokerage!=null){
					String hql = "update  AgentBrokerage set charge = charge + :newCharge,totalCharge = totalCharge + :newCharge where agentId = :agentId and state = 1";

					HashMap params = new HashMap();
					params.put("newCharge", order.getBrokerage()); 
					params.put("agentId", agentId); 
					agentBrokerageDao.executeHql(hql, params);
					AgentBrokerageDtl dtl = new AgentBrokerageDtl();
					dtl.setAgentId(agentId);
					dtl.setBrokerageId(agentBrokerage.getId()); 
					dtl.setOrderId(order.getId());
					dtl.setProductId(order.getProductId());
					dtl.setProductTariff(order.getTariff());
					dtl.setRate(order.getRate());
					dtl.setCharge(order.getBrokerage());
					agentBrokerageDtlDao.save(dtl);
				}
			}
		}
    }

	@Override
    public void productOrderFail(ProductOrder order) {
		order.setOrderState(GlobalConstant.ORDER_STATE_FAIL_NOT_REFUND);
		productOrderDao.update(order);
    }
}
